package pattern.controller;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import pattern.WorkServiceTool;
import pattern.annontations.Log;
import pattern.annontations.Menu;
import pattern.annontations.Secure;
import pattern.cache.InitCache;
import pattern.config.session.SystemCacheManage;
import pattern.constant.DefaultSystemConstant;
import pattern.currentsession.ContextLocalCache;
import pattern.dto.User;
import pattern.dto.UserOfRole;
import pattern.dto.model.system.*;
import pattern.dto.response.system.UserPageResponse;
import pattern.dto.response.system.UserResponse;
import pattern.enums.dict.common.LogBusinessTypeEnum;
import pattern.exception.AssertTool;
import pattern.exception.PatternException;
import pattern.feign.EmailFeign;
import pattern.feign.SmsFeign;
import pattern.feign.SocketFeign;
import pattern.limitconfig.RateLimiter;
import pattern.model.BaseIdModel;
import pattern.result.ResponseData;
import pattern.result.ResponsePage;
import pattern.result.ResponseResultStatus;
import pattern.routing.WorkMainApiRouting;
import pattern.utils.CollectionUtil;
import pattern.utils.SpringTool;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Simon
 * @date 2020-08-21
 */
@Api(tags = "用户管理")
@RestController
@RequestMapping(WorkMainApiRouting.User.BASE)
@Menu(menuName = "user", menuUri = "user", foundational = false)
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Secure
@Slf4j
public class UserController {

    private final SmsFeign smsFeign;
    private final EmailFeign emailFeign;

    @RateLimiter(value = 50)
    @ApiOperation(value = "查询")
    @GetMapping(WorkMainApiRouting.User.SEARCH)
    @Secure(actionUri = "user:search", actionName = "search", actionNote = "user")
    public ResponsePage<UserPageResponse> search(UserPageModel userSearchModel) {
        return WorkServiceTool.getUserService().pageResponse(userSearchModel, UserPageResponse.class);
    }

    @ApiOperation(value = "详情")
    @GetMapping(value = {"/{id}", "/"})
    @Secure(actionUri = "user:search")
    public ResponseData<UserResponse> detail(@PathVariable(value = "id", required = false) Integer id) {
        var user = WorkServiceTool.getUserService().getById(new BaseIdModel<>(id));
        UserResponse userResponse = new UserResponse().setUser(user);
        userResponse.setRoles(WorkServiceTool.getRoleService().list());
        if (Objects.nonNull(user)) {
            var roleIds = WorkServiceTool.getUserOfRoleService().getUserRole(user.getWorkerId()).stream().map(UserOfRole::getRoleId).collect(Collectors.toList());
            userResponse.setRoleIds(roleIds);
        }
        return new ResponseData<>(userResponse);
    }

/*    @ApiOperation(value = "发送socket消息给用户", notes = "rocketMq测试")
    @GetMapping(WorkMainApiRouting.User.SEND_MESSAGE)
    @Secure(actionUri = "user:send_message", actionName = "send_message", actionNote = "user")
    public ResponseData<Boolean> send(@RequestParam String msg) {
        try {
            SendMessageModel sendMessageModel = new SendMessageModel();
            //所有在线work用户
            HashSet<Integer> userIds = initCache.socketSession.GET(UserTypeEnum.WORK.getCode()).getValue();
            sendMessageModel.setUserIds(userIds);
            sendMessageModel.setMsgBody(msg);
            sendMessageModel.setTopic(WebSocketConstant.SESSION_PUSH_SERVER);
            SendResult sendResult = mqProducerSendService.send(SubscribeTopicEnum.SEND_MESSAGE_TO_USER_PUSH, sendMessageModel);
            if (sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
                return new ResponseData<>(Boolean.TRUE);
            } else {
                log.error("发送mq消息失败:{}", sendResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResponseData<>(Boolean.TRUE);
    }*/

   /* @ApiOperation(value = "新增用户",notes = "审批流测试")
    @PostMapping(WorkMainApiRouting.User.ADD_USER)
    @Secure(actionUri = "user:add_user", actionName = "add", actionNote = "user")
    public ApprovalResult addUser(@RequestBody UserAddModel user) throws PatternException {
        ApprovalResult approvalResult = WorkServiceTool.getUserService().addUser(new int[10], user);
        return approvalResult;
    }*/

    @ApiOperation(value = "修改状态")
    @PutMapping(WorkMainApiRouting.User.CHANGE_STATUS)
    @Secure(actionUri = "user:edit", actionName = "edit", actionNote = "user")
    public ResponseData<Boolean> changeStatus(@RequestBody UserChangeStatusAddModel model) throws PatternException {
        if (model.getId() <= 0) {
            return new ResponseData<>(ResponseResultStatus.BUILT);
        }
        return WorkServiceTool.getUserService().changeStatus(model);
    }

    @ApiOperation(value = "编辑用户")
    @PutMapping
    @Secure(actionUri = "user:edit", actionName = "edit", actionNote = "user")
    public ResponseData<Boolean> updateUser(@Valid @RequestBody UserAddOrEditModel model) throws PatternException {
        if (model.getId() <= 0) {
            return new ResponseData<>(ResponseResultStatus.BUILT);
        }
        if (CollectionUtil.isNotEmpty(model.getRoleIds())) {
            WorkServiceTool.getUserOfRoleService().editUserRole(model);
            SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        }
        model.setPsw(DigestUtil.bcrypt(model.getPsw()));
        var result = WorkServiceTool.getUserService().updateById(model);
        return new ResponseData<>(Objects.nonNull(result));
    }

    public static void main(String[] args) {
        System.out.println(DigestUtil.bcrypt("123456"));
    }

    @ApiOperation(value = "新增用户")
    @PostMapping
    @Secure(actionUri = "user:add", actionName = "add", actionNote = "user")
    @Log(title = "用户管理", name = "新增", businessType = LogBusinessTypeEnum.ADD)
    public ResponseData<Boolean> addUser(@RequestBody UserAddOrEditModel model) throws PatternException {
        ResponseData<Integer> result = WorkServiceTool.getUserService().saveUser(model);
        if (CollectionUtil.isNotEmpty(model.getRoleIds())) {
            model.setWorkerId(result.getData());
            WorkServiceTool.getUserOfRoleService().editUserRole(model);
            SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        }
        return new ResponseData<>(Boolean.TRUE);
    }

    @ApiOperation(value = "手机号码注册")
    @PostMapping(WorkMainApiRouting.User.PHONE_REGISTER)
    @Secure(value = -1)
    @GlobalTransactional
    public ResponseData<Boolean> phoneRegister(@Valid @RequestBody UserRegisterModel model) throws PatternException {
        //验证验证码是否正确
        var register = smsFeign.checkCode("register", model.getPhone(), model.getCode());
        AssertTool.isTrue(Objects.nonNull(register)&& register.isSuccess(), "验证码输入错误");
        //手机号码是否存在
        var one = WorkServiceTool.getUserService().getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, model.getPhone()));
        AssertTool.isTrue(Objects.isNull(one), "手机号码在系统中已存在");
        //添加数据
        ResponseData<Integer> result = WorkServiceTool.getUserService().register(model);
        if (result.getData() > 0) {
            //添加用户角色
            UserAddOrEditModel userAddOrEditModel = new UserAddOrEditModel();
            userAddOrEditModel.setWorkerId(result.getData());
            userAddOrEditModel.setDeptId(DefaultSystemConstant.DEFAULT_COMPANY);
            userAddOrEditModel.setRoleIds(List.of(DefaultSystemConstant.THIRD_ROLE));
            WorkServiceTool.getUserOfRoleService().editUserRole(userAddOrEditModel);
            SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        }
        return new ResponseData<>(Boolean.TRUE);
    }

    @ApiOperation(value = "邮箱验证注册")
    @PostMapping("/user/email_register")
    @Secure(value = -1)
    @GlobalTransactional
    public ResponseData<Boolean> emailRegister(@Valid @RequestBody UserRegisterModel model) throws PatternException {
        //验证验证码是否正确
        var register = emailFeign.checkCode(model.getEmail(), model.getCode());
        AssertTool.isTrue(Objects.nonNull(register)&& register.isSuccess(), "验证码输入错误");
        //邮箱是否存在
        var one = WorkServiceTool.getUserService().getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, model.getEmail()));
        AssertTool.isTrue(Objects.isNull(one), "邮箱在系统中已存在");
        var two = WorkServiceTool.getUserService().getOne(new LambdaQueryWrapper<User>().eq(User::getWorkerAccount, model.getEmail()));
        AssertTool.isTrue(Objects.isNull(two), "邮箱在系统中已存在");
        //添加数据
        ResponseData<Integer> result = WorkServiceTool.getUserService().register(model);
        if (result.getData() > 0) {
            //添加用户角色
            UserAddOrEditModel userAddOrEditModel = new UserAddOrEditModel();
            userAddOrEditModel.setWorkerId(result.getData());
            userAddOrEditModel.setDeptId(DefaultSystemConstant.DEFAULT_COMPANY);
            userAddOrEditModel.setRoleIds(List.of(DefaultSystemConstant.THIRD_ROLE));
            WorkServiceTool.getUserOfRoleService().editUserRole(userAddOrEditModel);
            SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        }
        return new ResponseData<>(Boolean.TRUE);
    }

    @ApiOperation(value = "找回密码")
    @PostMapping(WorkMainApiRouting.User.PHONE_FIND)
    @Secure(value = -1)
    public ResponseData<Boolean> phoneFind(@Valid @RequestBody UserRegisterModel model) throws PatternException {
        //验证验证码是否正确
        var find = smsFeign.checkCode("find", model.getPhone(), model.getCode());
        AssertTool.isTrue(Objects.nonNull(find)&& find.isSuccess(), "验证码输入错误");
        //手机号码是否存在
        var one = WorkServiceTool.getUserService().getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, model.getPhone()));
        AssertTool.isTrue(Objects.nonNull(one), "手机号码在系统中不存在");
        //修改密码
        WorkServiceTool.getUserService().updatePwd(model);
        return new ResponseData<>(Boolean.TRUE);
    }

    @ApiOperation(value = "删除")
    @DeleteMapping(WorkMainApiRouting.User.DELETE)
    @Secure(actionUri = "user:remove", actionName = "delete", actionNote = "user")
    public ResponseData<Boolean> delete(@PathVariable Integer[] id) {
        if (Arrays.stream(id).anyMatch(e -> e <= 0)) {
            return new ResponseData<>(ResponseResultStatus.BUILT);
        }
        var responseData = WorkServiceTool.getUserService().delete(new BaseIdModel<>(id));
        SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        return responseData;
    }
    @ApiOperation(value = "注销")
    @DeleteMapping("/user/off")
    public ResponseData<Boolean> off() {
        var id = ContextLocalCache.get().getId();
        if(id!=null){
           // if (ContextLocalCache.get().getRoleId().contains(DefaultSystemConstant.DEFAULT_COMPANY)) {
                var responseData = WorkServiceTool.getUserService().delete(new BaseIdModel<>(new Integer[]{id}));
                SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
                return responseData;
        }
        return new ResponseData<>(false);
    }



}
